package com.example.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONObject;
import com.example.dao.NxQuestionInfoDao;
import com.example.dao.NxTestpaperInfoDao;
import com.example.entity.NxTestpaperInfo;
import com.example.exception.CustomException;
import com.example.vo.NxQuestionInfoVo;
import com.example.vo.NxTestpaperInfoVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class NxTestpaperInfoService {

    @Resource
    private NxQuestionInfoDao nxQuestionInfoDao;

    @Resource
    private NxTestpaperInfoDao nxTestpaperInfoDao;

    public NxTestpaperInfo add(NxTestpaperInfo nxTestpaperInfo) {
        nxTestpaperInfoDao.insertSelective(nxTestpaperInfo);
        return nxTestpaperInfo;
    }

    /**
     * 生成试卷
     *
     * @param nxTestpaperInfoVo
     * @return
     */
    public NxTestpaperInfo generatePaper(NxTestpaperInfoVo nxTestpaperInfoVo) {
        // 试卷的type
        String type = nxTestpaperInfoVo.getType();
        List<NxQuestionInfoVo> finalSelectQuestions = CollUtil.newArrayList();
        if (nxTestpaperInfoVo.getSelectQuestion() != null) {
            List<NxQuestionInfoVo> selectQuestions = nxQuestionInfoDao.findByQuestionType("单选题", type);
            if (nxTestpaperInfoVo.getSelectQuestion() <= 0) {
                throw new CustomException("-1", "单选题设置需大于0");
            }
            if (nxTestpaperInfoVo.getSelectQuestion() > selectQuestions.size()) {
                throw new CustomException("-1", "单选题库数量不足");
            }
            // 选择题题目集合
            List<Integer> selectIndexList = getIndexList(selectQuestions.size(), nxTestpaperInfoVo.getSelectQuestion());
            selectIndexList.forEach(i -> finalSelectQuestions.add(selectQuestions.get(i)));
        }
        List<NxQuestionInfoVo> finalJudgeQuestions = CollUtil.newArrayList();
        if (nxTestpaperInfoVo.getJudgeQuestion() != null) {
            List<NxQuestionInfoVo> judgeQuestions = nxQuestionInfoDao.findByQuestionType("判断题", type);
            if (nxTestpaperInfoVo.getJudgeQuestion() <= 0) {
                throw new CustomException("-1", "判断题设置需大于0");
            }
            if (nxTestpaperInfoVo.getJudgeQuestion() > judgeQuestions.size()) {
                throw new CustomException("-1", "判断题库数量不足");
            }
            // 判断题题目集合
            List<Integer> judgeIndexList = getIndexList(judgeQuestions.size(), nxTestpaperInfoVo.getJudgeQuestion());
            judgeIndexList.forEach(i -> finalJudgeQuestions.add(judgeQuestions.get(i)));
        }

        List<NxQuestionInfoVo> finalAnswerQuestions = CollUtil.newArrayList();
        if (nxTestpaperInfoVo.getAnswerQuestion() != null) {
            List<NxQuestionInfoVo> answerQuestions = nxQuestionInfoDao.findByQuestionType("简答题", type);
            if (nxTestpaperInfoVo.getAnswerQuestion() <= 0) {
                throw new CustomException("-1", "简答题设置需大于0");
            }
            if (nxTestpaperInfoVo.getAnswerQuestion() > answerQuestions.size()) {
                throw new CustomException("-1", "简答题库数量不足");
            }

            // 简答题题题目集合
            List<Integer> answerIndexList = getIndexList(answerQuestions.size(), nxTestpaperInfoVo.getAnswerQuestion());
            answerIndexList.forEach(i -> finalAnswerQuestions.add(answerQuestions.get(i)));
        }
        // 多选题
        List<NxQuestionInfoVo> finalMulSelectQuestions = CollUtil.newArrayList();
        if (nxTestpaperInfoVo.getMulSelectQuestion() != null) {
            List<NxQuestionInfoVo> mulSelectQuestions = nxQuestionInfoDao.findByQuestionType("多选题", type);
            if (nxTestpaperInfoVo.getMulSelectQuestion() <= 0) {
                throw new CustomException("-1", "多选题设置需大于0");
            }
            if (nxTestpaperInfoVo.getMulSelectQuestion() > mulSelectQuestions.size()) {
                throw new CustomException("-1", "多选题库数量不足");
            }

            // 多选题题题目集合
            List<Integer> answerIndexList = getIndexList(mulSelectQuestions.size(), nxTestpaperInfoVo.getMulSelectQuestion());
            answerIndexList.forEach(i -> finalMulSelectQuestions.add(mulSelectQuestions.get(i)));
        }
        // 填空题
        List<NxQuestionInfoVo> finalFillQuestions = CollUtil.newArrayList();
        if (nxTestpaperInfoVo.getFillQuestion() != null) {
            List<NxQuestionInfoVo> fillQuestions = nxQuestionInfoDao.findByQuestionType("填空题", type);
            if (nxTestpaperInfoVo.getFillQuestion() <= 0) {
                throw new CustomException("-1", "填空题设置需大于0");
            }
            if (nxTestpaperInfoVo.getFillQuestion() > fillQuestions.size()) {
                throw new CustomException("-1", "填空题库数量不足");
            }

            // 填空题题题目集合
            List<Integer> answerIndexList = getIndexList(fillQuestions.size(), nxTestpaperInfoVo.getFillQuestion());
            answerIndexList.forEach(i -> finalFillQuestions.add(fillQuestions.get(i)));
        }
        // 校验，不能全部为空
        if (CollectionUtil.isEmpty(finalSelectQuestions) && CollectionUtil.isEmpty(finalJudgeQuestions) && CollectionUtil.isEmpty(finalAnswerQuestions)
                && CollectionUtil.isEmpty(finalMulSelectQuestions) && CollectionUtil.isEmpty(finalFillQuestions)) {
            throw new CustomException("-1", "请至少确定一种题型数量");
        }
        // 生成试卷html
        Map<String, String> map = getPaperHtml(nxTestpaperInfoVo, finalSelectQuestions, finalJudgeQuestions, finalAnswerQuestions,
                finalMulSelectQuestions, finalFillQuestions);
        nxTestpaperInfoVo.setContent(map.get("page"));
        nxTestpaperInfoVo.setAnswer(map.get("answer"));
        //插入表
        add(nxTestpaperInfoVo);
        return nxTestpaperInfoVo;
    }

    /**
     * 生成试卷html
     *
     * @param selects
     * @param judges
     * @param answers
     * @return
     */
    private Map<String, String> getPaperHtml(NxTestpaperInfoVo nxTestpaperInfoVo, List<NxQuestionInfoVo> selects,
                                             List<NxQuestionInfoVo> judges, List<NxQuestionInfoVo> answers,
                                             List<NxQuestionInfoVo> mulSelect, List<NxQuestionInfoVo> fill) {
        Map<String, String> map = new HashMap<>();

        StringBuilder pageBuilder = new StringBuilder();
        JSONObject answerBuilder = new JSONObject();
        pageBuilder.append("<div class=\"panel-heading\">\n")
                .append("<span style=\"font-size: 14px\">试卷名称：</span><span style=\"color: orangered\">" + nxTestpaperInfoVo.getName() + "</span>\n")
                .append("<span style=\"font-size: 14px; margin-left: 20px\">试卷编号：</span><span style=\"color: orangered\">" + nxTestpaperInfoVo.getCode() + "</span>\n")
                .append("<span style=\"font-size: 14px; margin-left: 20px\">考试剩余时间：</span><span id=\"time\" style=\"color: orangered\">" + nxTestpaperInfoVo.getTime() + "分</span>\n")
                .append("</div>\n")
                .append("<div class=\"panel-body\">\n")
                .append("<div style=\"border: 1px solid #1E9FFF;\">\n");

        int count = 0;
        if (!CollectionUtil.isEmpty(selects)) {
            pageBuilder.append("<div class=\"examine-title\"><b>选择题（共" + selects.size() + "题，每题" + selects.get(0).getScore() + "分）</b></div>\n");
            for (NxQuestionInfoVo select : selects) {
                count++;
                String options = select.getOptions();
                String[] arr = options.split(",");
                pageBuilder.append("<div class=\"examine-item\" style=\"color: darkblue;\">" + select.getName() + "</div>\n")
                        .append("<div class=\"examine-item\" style=\"color: black;\">\n")
                        .append("<label for=\"" + count + "-a\"><input id=\"" + count + "-a\" name=\"" + count + "\" type=\"radio\" value=\"A\" />A. " + arr[0] + "</label>\n")
                        .append("<label for=\"" + count + "-b\"><input id=\"" + count + "-b\" name=\"" + count + "\" type=\"radio\" value=\"B\" />B. " + arr[1] + "</label>\n")
                        .append("<label for=\"" + count + "-c\"><input id=\"" + count + "-c\" name=\"" + count + "\" type=\"radio\" value=\"C\" />C. " + arr[2] + "</label>\n")
                        .append("<label for=\"" + count + "-d\"><input id=\"" + count + "-d\" name=\"" + count + "\" type=\"radio\" value=\"D\" />D. " + arr[3] + "</label>\n")
                        .append("</div>\n")
                        .append("<div class=\"examine-item solution\" style=\"display: none\">答案：" + select.getAnswer() + "</div>\n");

                answerBuilder.set(count + "_" + select.getScore(), select.getAnswer());
            }
        }

        if (!CollectionUtil.isEmpty(mulSelect)) {
            pageBuilder.append("<div class=\"examine-title\"><b>多选题（共" + mulSelect.size() + "题，每题" + mulSelect.get(0).getScore() + "分）</b></div>\n");
            for (NxQuestionInfoVo select : mulSelect) {
                count++;
                String options = select.getOptions();
                String[] arr = options.split(",");
                pageBuilder.append("<div class=\"examine-item\" style=\"color: darkblue;\">" + select.getName() + "</div>\n")
                        .append("<div class=\"examine-item\" style=\"color: black;\">\n")
                        .append("<label for=\"" + count + "-a\"><input id=\"" + count + "-a\" name=\"" + count + "\" type=\"checkbox\" value=\"A\" />A. " + arr[0] + "</label>\n")
                        .append("<label for=\"" + count + "-b\"><input id=\"" + count + "-b\" name=\"" + count + "\" type=\"checkbox\" value=\"B\" />B. " + arr[1] + "</label>\n")
                        .append("<label for=\"" + count + "-c\"><input id=\"" + count + "-c\" name=\"" + count + "\" type=\"checkbox\" value=\"C\" />C. " + arr[2] + "</label>\n")
                        .append("<label for=\"" + count + "-d\"><input id=\"" + count + "-d\" name=\"" + count + "\" type=\"checkbox\" value=\"D\" />D. " + arr[3] + "</label>\n")
                        .append("</div>\n")
                        .append("<div class=\"examine-item solution\" style=\"display: none\">答案：" + select.getAnswer() + "</div>\n");

                answerBuilder.set(count + "_" + select.getScore(), select.getAnswer());
            }
        }

        if (!CollectionUtil.isEmpty(judges)) {
            pageBuilder.append(" <div class=\"examine-title\"><b>判断题（共" + judges.size() + "题，每题" + judges.get(0).getScore() + "分）</b></div>\n");

            for (NxQuestionInfoVo judge : judges) {
                count++;
                pageBuilder.append("<div class=\"examine-item\" style=\"color: darkblue;\">" + judge.getName() + "</div>\n")
                        .append("<div class=\"examine-item\" style=\"color: black;\">\n")
                        .append("<label for=\"" + count + "-a\"><input id=\"" + count + "-a\" name=\"" + count + "\" type=\"radio\" value=\"正确\" />正确</label>\n")
                        .append("<label for=\"" + count + "-b\"><input id=\"" + count + "-b\" name=\"" + count + "\" type=\"radio\" value=\"错误\" />错误</label>\n")
                        .append("</div>\n")
                        .append("<div class=\"examine-item solution\" style=\"display: none\">答案：" + judge.getAnswer() + "</div>\n");

                answerBuilder.set(count + "_" + judge.getScore(), judge.getAnswer());
            }
        }

        if (!CollectionUtil.isEmpty(fill)) {
            pageBuilder.append(" <div class=\"examine-title\"><b>填空题（共" + fill.size() + "题，每题" + fill.get(0).getScore() + "分）</b></div>\n");

            for (NxQuestionInfoVo answer : fill) {
                count++;
                pageBuilder.append("<div class=\"examine-item\" style=\"color: darkblue;\">" + answer.getName() + "</div>\n")
                        .append("<div class=\"examine-item\" style=\"color: black;\">\n")
                        .append("<input name=\"" + count + "\" style=\"padding: 5px\">\n")
                        .append("</div>\n")
                        .append("<div class=\"examine-item solution\" style=\"display: none\">答案：" + answer.getAnswer() + "</div>\n");

                answerBuilder.set(count + "_" + answer.getScore(), answer.getAnswer());
            }
        }

        if (!CollectionUtil.isEmpty(answers)) {
            pageBuilder.append(" <div class=\"examine-title\"><b>简答题（共" + answers.size() + "题，每题" + answers.get(0).getScore() + "分）</b></div>\n");

            for (NxQuestionInfoVo answer : answers) {
                count++;
                pageBuilder.append("<div class=\"examine-item\" style=\"color: darkblue;\">" + answer.getName() + "</div>\n")
                        .append("<div class=\"examine-item\" style=\"color: black;\">\n")
                        .append("<textarea name=\"" + count + "\" cols=\"100\" rows=\"5\" style=\"padding: 5px\"></textarea>\n")
                        .append("</div>\n")
                        .append("<div class=\"examine-item solution\" style=\"display: none\">答案：" + answer.getAnswer() + "</div>\n");

                answerBuilder.set(count + "_" + answer.getScore(), answer.getAnswer());
            }
        }
        // cardBody结束的div
        pageBuilder.append("</div>\n");
        // 提交按钮
        pageBuilder.append("<div class=\"row\" style=\"text-align: center; padding: 10px 0\"><button class=\"btn\" id=\"submit\" onclick=\"submit()\">提交</button></div>\n");


        map.put("page", pageBuilder.toString());
        map.put("answer", answerBuilder.toString());
        return map;
    }

    /**
     * 从指定的total范围内获取count个不同的随机数
     *
     * @param total 范围
     * @param count 个数
     * @return 随机数集合
     */
    private List<Integer> getIndexList(int total, int count) {
        List<Integer> randoms = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            while (true) {
                int r = RandomUtil.randomInt(total);
                if (!randoms.contains(r)) {
                    randoms.add(r);
                    break;
                }
            }
        }
        return randoms;
    }

    public void delete(Long id) {
        nxTestpaperInfoDao.deleteByPrimaryKey(id);
    }

    public void update(NxTestpaperInfo nxTestpaperInfo) {
        nxTestpaperInfoDao.updateByPrimaryKeySelective(nxTestpaperInfo);
    }

    public NxTestpaperInfo findById(Long id) {
        return nxTestpaperInfoDao.selectByPrimaryKey(id);
    }

    public List<NxTestpaperInfoVo> findAll() {
        return nxTestpaperInfoDao.findByName("all");
    }

    public PageInfo<NxTestpaperInfoVo> findPage(String name, Integer pageNum, Integer pageSize, HttpServletRequest request) {
        PageHelper.startPage(pageNum, pageSize);
        List<NxTestpaperInfoVo> all = findAllPage(request, name);
        return PageInfo.of(all);
    }

    public List<NxTestpaperInfoVo> findAllPage(HttpServletRequest request, String name) {
        return nxTestpaperInfoDao.findByName(name);
    }

    public NxTestpaperInfo findByCode(String code) {
        return nxTestpaperInfoDao.findByCode(code);
    }
}
